import { T_task } from '@/obj/class';
import { Tsrv, ifs, ts } from '@/services';
import { N_cPLDetails } from '../types';

class T_pldBase {
  // 主组件箱
  private compBox: ifs.I_compBox;

  // 主组件ID
  private compID: string;

  // 主组件实例
  public self: N_cPLDetails.cPLDetails;

  // 产线轮询时间间隔
  public task: T_task = new T_task(5000);

  // 当前轮询是否开启
  public isOpenTask: boolean = false;

  // 产线明细管理实例
  public topBaseGrid: any = null;

  // 编码组
  public ecDetCodeList: string[] = [];

  // 是否自动生产
  public isAutoProduce: boolean = true;

  // 表名
  public tableName = {
    pLine: 'produc_line_mgmt', // 产线管理
    pLDetails: 'produc_line_detail_mgmt', // 产线明细管理
    gZDetails: 'hang_group_detail_mamt', // 挂组明细管理
    sSTime: 'simu_sche_time', // 仿真排程时间
    pLLog: 'product_line_log', // 产线日志
    hGDetails: 'hang_group_detail', // 挂组明细
    hGLog: 'hanggroup_log', // 挂组日志
    dLog: 'driving_log', // 行车日志
    pTLog: 'process_tank_log', // 工艺槽日志
    hGSupplementInfo: 'hg_supplement_info', // 挂组补充信息
    businessNumTbale: 'business_num_table', // 业务编号表
    dimensionQuery: 'dimension_query', // 维度查询
    alarmQuery: 'alarm_query', // 报警查询
    timeConversionConfig: 'time_conversion_config', // 时间换算配置
    processSettingParameters: 'view_process_setting_parameters', // 工艺设定参数
    scheRecordLog: 'schedule_record_log' // 排程记录日志
  };

  // 读写异常处理
  public handleException = {
    read: {
      hasWritten: false,
      count: 0
    },
    write: {
      count: 0
    }
  };

  // 过滤字段名
  public filterName = {
    ID: 'id',
    physicalNum: 'physical_num'
  };

  // 公共事件
  public commonEvent = {
    // 产线管理事件
    lMEvent: 'CA27AC8D9258ABB7',
    // 智能排产明细事件
    sMEvent: 'CDE43B4F5287CB25',
    // 仿真排程时间事件
    scheTime: 'MY_SCHEDULETIME',
    // 产线日志
    pLLogEvent: '2562C30646592A06',
    // 挂组日志
    hGLogEvent: 'DBFA5B165EC96B60',
    // 行车日志
    dLogEvent: '1A6C8D2A254AFFF0',
    // 工艺槽日志
    pTLogEvent: 'D869DB92BA61CEB9',
    // 更新任务信息
    updateTaskInfo: 'UPDATE_TASK_INFO',
    // 接收报警信息
    receiveAlarmInfo: 'RECEIVE_ALARM_INFO',
    // 接收产线配置信息
    receivePLConfigInfo: 'RECEIVE_PL_CONFIG_INFO'
  };

  // 事件参数，刷新使用
  public eventArg = [
    {
      type: 'refresh',
      content: {},
      listenType: 'default'
    }
  ];

  // 四个缓存位信息
  public fourCacheInfo: Map<string, N_cPLDetails.I_cacheInfo> = new Map([
    [
      '28号缓存位',
      {
        hangGroupId: {
          code: 'my353',
          value: null
        },
        cacheOrder: {
          code: 'my320',
          value: null
        },
        hangGroupStatus: {
          code: 'my3830',
          value: null
        },
        tempIsSatisfied: {
          code: 'my3834',
          value: null
        }
      }
    ],
    [
      '29号缓存位',
      {
        hangGroupId: {
          code: 'my354',
          value: null
        },
        cacheOrder: {
          code: 'my321',
          value: null
        },
        hangGroupStatus: {
          code: 'my3831',
          value: null
        },
        tempIsSatisfied: {
          code: 'my3835',
          value: null
        }
      }
    ],
    [
      '30号缓存位',
      {
        hangGroupId: {
          code: 'my355',
          value: null
        },
        cacheOrder: {
          code: 'my322',
          value: null
        },
        hangGroupStatus: {
          code: 'my3832',
          value: null
        },
        tempIsSatisfied: {
          code: 'my3836',
          value: null
        }
      }
    ],
    [
      '31号缓存位',
      {
        hangGroupId: {
          code: 'my356',
          value: null
        },
        cacheOrder: {
          code: 'my323',
          value: null
        },
        hangGroupStatus: {
          code: 'my3833',
          value: null
        },
        tempIsSatisfied: {
          code: 'my3837',
          value: null
        }
      }
    ]
  ]);

  // 主组件created里初始化
  public init(self: N_cPLDetails.cPLDetails, compBoxInfo: ifs.I_compBoxInfo) {
    this.self = self;
    this.compBox = compBoxInfo.TcompBox;
    this.compID = compBoxInfo.compID;
  }

  // 修改数据,根据传入filter字段修改
  public modifyData(
    tableName: string,
    filterName: string,
    rows: Array<ifs.I_fv[]>
  ): Promise<boolean> {
    const ctd = new ts.T_ctdArg();
    ctd
      .setTableName(tableName)
      .setDbType(Tsrv.globalVar.dbType.MYSQL)
      .setRule({} as ifs.I_rule);
    const datas = [];
    rows.forEach(row => {
      const fileter = {};
      row.forEach(el => {
        if (el.field === filterName) {
          fileter[filterName] = el.value;
        }
      });
      const ctdUpdData = new ts.T_ctdUpdData();
      ctdUpdData.setFilter(fileter);
      ctdUpdData
        .setDataRule({} as ifs.I_rule)
        .setFileInfo({})
        .setRowData(...row.filter(el => el.field !== filterName));
      datas.push(ctdUpdData);
    });
    ctd.setUpdRecDataMany(...datas);
    return new Promise((resolve, reject) => {
      Tsrv.batRows(ctd).then(([b, res, msg]) => {
        if (!b) {
          this.self.$msg(msg);
          reject(false);
        } else {
          resolve(true);
          if (tableName === this.tableName.pLDetails) {
            // 加入当前过滤条件并刷新表格
            this.topBaseGrid.GT_editor.loadTableData().then(() => {
              this.self.$bus.$emit('UPD_PL_DETAILS');
              // 新上准备就绪挂组
              const arr = this.topBaseGrid.cloudData.filter(
                el => el.f_status === 2
              );
              if (arr.length > 0) {
                this.self.topTableData = this.topBaseGrid.cloudData;
              }
            });
          }
        }
      });
    });
  }

  // 新增表格数据
  public addTableData(
    tableName: string,
    rows: Array<ifs.I_fv[]>
  ): Promise<boolean> {
    const ctd = new ts.T_ctdArg();
    ctd
      .setTableName(tableName)
      .setDbType(Tsrv.globalVar.dbType.MYSQL)
      .setRule({} as ifs.I_rule);
    const data = [];
    rows.forEach(row => {
      const baseData = new ts.T_baseData();
      baseData
        .setDataRule({} as ifs.I_rule)
        .setFileInfo({})
        .setRowData(...row);
      data.push(baseData);
    });
    ctd.setInsRecDataMany({}, ...data);
    return new Promise((resolve, reject) => {
      Tsrv.batRows(ctd).then(([b, res, msg]) => {
        if (!b) {
          this.self.$msg(msg);
          reject(false);
        } else {
          resolve(true);
        }
      });
    });
  }

  // (毫秒0|秒1)转小时分钟秒
  public changeTimeFormat(time: number, type: number = 0) {
    const seconds = type === 0 ? Math.floor(time / 1000) : time;
    // const seconds = Math.floor(time / 1000);
    const hours = seconds > 3600 ? Math.floor(seconds / 3600) : 0;
    const minutes = seconds > 60 ? Math.floor((seconds % 3600) / 60) : 0;
    const secondsLeft = seconds > 0 ? seconds % 60 : 0;

    return `${hours.toString().padStart(2, '0')}时${minutes
      .toString()
      .padStart(2, '0')}分${secondsLeft.toString().padStart(2, '0')}秒`;
  }

  // 时间格式转换
  public addSecondsToTime(timeString: string, seconds: number) {
    // 解析时间字符串为 Date 对象
    const date = new Date(timeString);

    // 将秒数转换为毫秒数并加到 Date 对象上
    date.setMilliseconds(date.getMilliseconds() + seconds * 1000);

    // 格式化 Date 对象为所需的时间字符串
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始，需要加1
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const secondsPart = String(date.getSeconds()).padStart(2, '0');

    return `${year}-${month}-${day} ${hours}:${minutes}:${secondsPart}`;
  }

  // 发送事件
  public sendBusEvent(eventName: string, val: any) {
    Tsrv.reliablySendingBusEvent(eventName, this.self.$bus, 10, 100, ...val);
  }

  // 读取plc数据
  public readPlcData(
    codes: string[]
  ): Promise<N_cPLDetails.I_readResp['data'] | boolean> {
    return new Promise((resolve, reject) => {
      Tsrv.standardPostReq<N_cPLDetails.I_readResp, any>(
        { ecDetCodes: codes },
        Tsrv.url.scadaRead
      ).then(([readResp, err]) => {
        if (!Tsrv.noValue(err)) {
          this.self.$msg(err);
          this.self.sendLogOut({
            content: `${codes}读取失败，等待10秒后重试`,
            isErr: true
          });
          this.task.switchIntervalTime(10000); // 读取失败，等待10秒后重试
          reject(false);
        }
        if (!readResp.success) {
          this.self.$msg(readResp.msg);
          this.self.sendLogOut({
            content: `${codes}读取失败，等待10秒后重试`,
            isErr: true
          });
          this.task.switchIntervalTime(10000); // 读取失败，等待10秒后重试
          reject(false);
        }
        resolve(readResp.data);
      });
    });
  }

  public writePlcData(
    data: N_cPLDetails.I_writeCodeRes[],
    isRewrite = false
  ): Promise<boolean> {
    return new Promise((resolve, reject) => {
      Tsrv.standardPostReq<N_cPLDetails.I_writeResp, N_cPLDetails.I_writeRes>(
        {
          writeList: data
        },
        Tsrv.url.scadaWrite
      ).then(([res, e]) => {
        if (!res.success) {
          const codes = [];
          for (const item of data) {
            codes.push(item.ecDetCode);
          }
          this.self.sendLogOut({
            content: `${codes}写入失败`,
            isErr: true
          });
          this.self.$msg(res.msg);
          reject(false);
          if (isRewrite) {
            // 写入失败记录失败次数，延迟两秒后重新写入，两次均失败则停止写入
            this.handleException.write.count++;
            if (this.handleException.write.count < 2) {
              // 写入失败延迟两秒后重新写入
              setTimeout(() => {
                this.writePlcData(data, true);
              }, 2000);
            }
          }
        } else {
          // 写入成功
          this.handleException.write.count = 0;
          resolve(true);
        }
      });
    });
  }

  public doLoadData(tableName: string, filter = {}) {
    const gpd = new ts.T_getPartDataArg();
    gpd.setFilter(filter);
    gpd.setFunName(tableName);
    gpd.setTableName(tableName);
    gpd.setDbType(Tsrv.globalVar.dbType.MYSQL);
    gpd.setLang(this.self.$i18n.locale);
    gpd.setPage(1, 99999);
    gpd.setRule({} as ifs.I_rule);

    return Tsrv.getData(gpd);
  }

  public loadFilterList(
    field: string[],
    funName: string,
    filter = {}
  ): Promise<
    Array<{
      [key: string]: any;
    }>
  > {
    const gpfd: ts.T_GPFD = new ts.T_GPFD();
    gpfd
      .setLang(this.self.$i18n.locale || 'en-US')
      .setFunName(funName)
      .setTableName(funName)
      .setDbType(Tsrv.globalVar.dbType.MYSQL);
    gpfd.setFilter(filter).setAgreedFields(...field);

    return new Promise((resolve, reject) => {
      Tsrv.getData<any, ifs.I_GPFD>(gpfd)
        .then(r => {
          const [b, res, rows, msg] = r;
          resolve(rows);
        })
        .catch(err => {
          this.self.$msg(err);
        });
    });
  }
}
interface I_pldBase extends T_pldBase {}
export { I_pldBase, N_cPLDetails, T_pldBase, T_task, Tsrv, ifs, ts };
